/*
 * @Author: ws.s 
 * @Date: 2021-07-17 12:00:02 
 * @Last Modified by: ws.s
 * @Last Modified time: 2021-10-27 19:59:05
 */
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Collections;
using UnityEngine;
using WssUtils;
using DG.Tweening;
using System.Collections.Generic;
using UnityEngine.Events;



public class AudioName
{
    public static string HomeBGM = "HomeBgm";
    public static string GameBGM = "GameBgm";
    
    //按钮点击音效
    public static string Click = "Click";
    
    //丢弃道具音效
    public static string DiscardProp = "DiscardProp";
    //刷新道具音效
    public static string RefreshProp = "RefreshProp";
    //消除道具音效
    public static string RemoveProp = "RemoveProp";
    
    //放置房子音效
    public static string PlaceCity = "PlaceCity";
    
        
    //放置房子随机音效
    public static string CityPlace1 = "CityPlace1";
    public static string CityPlace2 = "CityPlace2";
    public static string CityPlace3 = "CityPlace3";
    
    //过关房子下降音效
    public static string PassCityDown = "PassCityDown";
    
    
    //合成房子音效
    public static string MergeCity = "MergeCity";
    
    //备战区生成音效
    public static string CreateCity = "CreateCity";
    
    //成就达成音效
    public static string Achievement = "Achievement";
}

/// <summary>
/// 声音管理器
/// v1.0.0 - 修复播放音效后，会改变其他音量的bug
/// v1.0.1 - 增加判定，IsPlayingSE ，判定是否其他音效在播放F
/// v1.1.0 - 增加AudioSourceCtrl 控制，可以单独控制一个游戏场景中的AudioSource
/// </summary>
public class AudioManager : SingletonMonoBehaviour<AudioManager>
{
    //public static AudioManager Instance = null;
    const string PATH_SE = "audio/se/";
    const string PATH_BGM = "audio/bgm/";

    public AudioSource curAudioSE; //当前的 audioSource
    public AudioSource curAudioBGM; //当前的背景音乐 audioSource

    // public Queue shortAudioPool; // 对象池子
    private AudioClip audioClip;
    public string curMusicName = "";
    private float volumeSE = 1;
    private float volumeBGM = 1;
    public bool canPlaySound = true;//音效控制开关
    public bool canPlayMusic = true;//音乐控制开关

    private float _pauseCacheMusicVolume = 0; //锁定音频

    public bool canPlayerShake = false;
    
    private Dictionary<string, float> _cacheTags = new Dictionary<string, float>();


    void Awake()
    {
        volumeBGM = PlayerPrefs.GetFloat("_audio_bgm_volume", 1.0f);
        volumeSE = PlayerPrefs.GetFloat("_audio_se_volume", 1.0f);
        canPlaySound = PlayerPrefs.GetInt("_can_play_sound", 1) == 1;
        canPlayMusic = PlayerPrefs.GetInt("_can_play_music", 1) == 1;
        canPlayerShake = PlayerPrefs.GetInt("_can_play_shake", 1) == 1;
        
        volumeBGM = 1;
        volumeSE = 1;
        curAudioSE = gameObject.AddComponent<AudioSource>();
        curAudioSE.loop = false;
        curAudioBGM = gameObject.AddComponent<AudioSource>();
        curAudioBGM.loop = true;
        AudioSourceCtrl.IsMuteAll = !canPlaySound;
    }

    public void SetSoundOpen(bool open)
    {
        canPlaySound = open;
        PlayerPrefs.SetInt("_can_play_sound", open ? 1 : 0);
        AudioSourceCtrl.IsMuteAll = !open;
        AudioSourceCtrl.onSoundSettings?.Invoke(!open);
    }


    public void SetMusicOpen(bool open, bool canResume = true)
    {
        canPlayMusic = open;
        PlayerPrefs.SetInt("_can_play_music", open ? 1 : 0);

        if (open && curAudioBGM.clip != null)
        {
            curAudioBGM.mute = false;
        }
        else
        if (!open && curAudioBGM.clip != null)
        {
            curAudioBGM.mute = true;
        }

    }

    public void SetShakeOpen(bool open, bool canResume = true)
    {
        canPlayerShake = open;
        PlayerPrefs.SetInt("_can_play_shake", open ? 1 : 0);
    }

    public void PlayBGM(string fileName, float volume = 1.0f, bool fade = false, float fadeTime = 0.5f)
    {
        curMusicName = fileName;
        audioClip = Resources.Load(PATH_BGM + fileName) as AudioClip;
        curAudioBGM.clip = audioClip;
        curAudioBGM.volume = volume * volumeBGM;
        curAudioBGM.Play();
        _pauseCacheMusicVolume = curAudioBGM.volume;

        if (fade)
        {
            curAudioBGM.DOFade(volume * volumeBGM, fadeTime);
        }

        if (!canPlayMusic)
        {
            curAudioBGM.mute = true;
        }

    }

    public void StopBGM(bool fade = false, float fadeTime = 0.5f)
    {
        if (fade)
        {
            curAudioBGM.DOFade(0, fadeTime).OnComplete(() =>
            {
                curAudioBGM.Stop();
                curMusicName = "";
            });
        }
        else
        {
            curAudioBGM.Stop();
            curMusicName = "";
        }
    }

    public void DelayPlayAtPoint(float delayTime, string fileName, Vector3 position)
    {
        if (!canPlaySound) return;
        StartCoroutine(_DelayPlayAtPoint(fileName, position, delayTime));
    }
    private IEnumerator _DelayPlayAtPoint(string fileName, Vector3 position, float delayTime = 0.1f)
    {
        yield return new WaitForSeconds(delayTime);
        PlayAtPoint(fileName, position);
    }

    //在某个坐标点播放音效
    public void PlayAtPoint(string fileName, Vector3 position)
    {
        if (!canPlaySound || volumeSE <= 0) return;
        audioClip = Resources.Load(PATH_SE + fileName) as AudioClip;
        AudioSource.PlayClipAtPoint(audioClip, position);
    }

    /// <summary>
    /// 播放音效
    /// </summary>
    /// <param name="fileName">文件名</param>
    /// <param name="volume">音量</param>
    /// <param name="onlyOnceStay">是否同时只允许播放这一个音效</param>
    public void Play(string fileName, float volume = 1.0f, bool onlyOnceStay = false)
    {
        if (!canPlaySound || volumeSE <= 0) return;
        audioClip = Resources.Load(PATH_SE + fileName) as AudioClip;
        if (audioClip == null)
        {
            Debug.LogWarning("Audio Loaded Failed:" + fileName);
            return;
        }

        if (onlyOnceStay)
        {
            if (_cacheTags.ContainsKey(fileName)) return;
            _cacheTags.Add(fileName, audioClip.length);
        }
        curAudioSE.PlayOneShot(audioClip, volume);
    }

    /// <summary>
    /// 支持延迟播放声音
    /// </summary>
    /// <param name="delayTime">延迟时间</param>
    /// <param name="fileName">文件名</param>
    /// <param name="volume">音量</param>
    public void DelayPlay(float delayTime, string fileName, float volume = 1.0f)
    {
        if (!canPlaySound) return;
        StartCoroutine(_DelayPlay(fileName, volume, delayTime));
    }

    private IEnumerator _DelayPlay(string fileName, float volume = 1.0f, float delayTime = 0.1f)
    {
        yield return new WaitForSeconds(delayTime);
        Play(fileName, volume);
    }

#if UNITY_WEBGL
    /// <summary>
    /// web平台的特殊情况，进入后台时暂停音乐，回复后还原重新播放音乐
    /// </summary>
    private string _webPauseBgmName = "";

#endif

    [ContextMenu("暂停BGM")]
    public void PauseBGM()
    {
        //FIX web只能强制暂停音乐
#if UNITY_WEBGL
        _webPauseBgmName = AudioManager.Instance.curMusicName;
        AudioManager.Instance.StopBGM();
#else
        volumeBGM = 1;
        _pauseCacheMusicVolume = this.curAudioBGM.volume;
        this.curAudioBGM.mute = true;
#endif
    }

    [ContextMenu("恢复BGM")]
    public void RemuseBGM()
    {
#if UNITY_WEBGL
        if (canPlayMusic)
        {
            if (!string.IsNullOrEmpty(_webPauseBgmName))
            {
                PlayBGM(_webPauseBgmName);
            }
        }
        _webPauseBgmName = "";
#else
        volumeBGM = 1;
        if (!canPlayMusic)
        {
            this.curAudioBGM.mute = true;
            return;
        }
        else
        {
            this.curAudioBGM.mute = false;
        }
#endif
    }

    public void OnApplicationPause(bool pauseStatus)
    {
        if (pauseStatus)
            PauseBGM();
        else
            RemuseBGM();
    }

    /// <summary>
    /// 是否有任意音效在播放
    /// </summary>
    /// <returns></returns>
    public bool IsPlayingSE()
    {
        return curAudioSE.isPlaying;
    }

    /// <summary>
    /// 停止音效播放
    /// </summary>
    public void StopSE()
    {
        curAudioSE.Stop();
    }

    public void StopAll()
    {
        StopBGM();
        StopSE();
    }

    private void Update()
    {
        if (_cacheTags.Count > 0)
        {
            List<string> cacheList = new List<string>();
            var keys = _cacheTags.Keys.ToArray();
            for (int i = 0; i < keys.Length; i++)
            {
                string key = keys[i];

                if (_cacheTags[key] >= 0)
                {
                    _cacheTags[key] -= Time.deltaTime;
                    if (_cacheTags[key] <= 0)
                    {
                        _cacheTags.Remove(key);
                    }
                }


            }

        }
    }



}
